/**
 * Copyright (c) 2017,安徽皖通科技股份有限公司 All rights reserved.
 *
 * @data:2017年10月16日
 * @author:MaShibo
 */
package com.wttech.dzzf.process.service.transaction;

import com.wtkj.vo.dzzf.base.kfwd.TransIn;
import com.wttech.dzzf.process.dao.RechargeInfoDao;
import com.wttech.dzzf.process.dao.TransferUserInfoDao;
import com.wttech.dzzf.process.model.Organization;
import com.wttech.dzzf.process.model.transaction.Recharge;
import com.wttech.dzzf.process.service.base.BaseInfoService;
import com.wttech.dzzf.process.service.user.UserDetailInfosCreatorService;
import com.wttech.dzzf.process.service.user.UserInfosCreatorService;
import com.wttech.dzzf.process.util.BusinessUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

/**
 * 创建充值记录服务
 *
 * @author MaShibo
 * @date 2017年10月16日
 */
@Service
public class RechargeInfosCreatorService {


    private static final Logger LOGGER = LoggerFactory.getLogger(RechargeInfosCreatorService.class);

    private static final String DEFAULT_DATETIME_PATTERN = "yyyyMMddHHmmss";

    /**
     * 充值序列号的长度
     */
    private static final int DEFAULT_SEQNO_LENGTH = 2;

    /**
     * 默认每次处理数量
     */
    private static final int DEFAULT_PROCESS_NUM = 10000;

    private static final BigDecimal DEFAULT_FEN_VALUE = new BigDecimal("100");

    @Resource
    private RechargeInfoDao rechargeInfoDao;

    @Resource
    private TransferUserInfoDao transferUserInfoDao;

    @Resource
    private ThreadPoolTaskExecutor executor;

    @Resource
    private BaseInfoService baseInfoService;

    @Resource
    private UserInfosCreatorService userInfosCreatorService;

    /**
     * 用于保存充值序列号
     */
    private Map<String, Integer> transinSeqNoMap = new ConcurrentHashMap<>();

    /**
     * 待收集数据日期
     */
    private List<String> dateStrs;

    /**
     * 创建充值记录信息
     */
    private void processRechargeInfos() {
        if (CollectionUtils.isEmpty(dateStrs)) {
            LOGGER.info("未指定要收集数据的日期");
            return;
        }
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("待收集日期：{}", StringUtils.join(dateStrs, ", "));
        }
        int total = rechargeInfoDao.queryRechargeInfosNum(dateStrs);
        LOGGER.info("共{}条充值记录", total);
        int count = (int) Math.ceil((double) total / DEFAULT_PROCESS_NUM);
        LOGGER.info("共需要执行{}次", count);
        List<Future<Void>> futures = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            int num = i + 1;
            LOGGER.info("第{}次开始执行", num);
            int startRow = i * DEFAULT_PROCESS_NUM + 1;
            int endRow = (i + 1) * DEFAULT_PROCESS_NUM;
            List<TransIn> transIns = rechargeInfoDao.queryRechargeInfos(dateStrs, startRow, endRow);
            transIns.forEach(transIn -> futures.add(executor.submit(() -> {
                processSingleTransin(transIn);
                return null;
            })));
            LOGGER.info("第{}次结束执行", num);
        }
        baseInfoService.getFutureResult(futures);
        LOGGER.info("充值记录创建完毕");
        executor.shutdown();
    }

    /**
     * 处理单条充值记录信息
     *
     * @param transIn DZZF充值记录信息
     * @return 充值记录信息
     */
    Recharge processSingleTransin(TransIn transIn) {
        Recharge recharge = buildRechargeInfo(transIn);
        String rechargeId = recharge.getId();
        int rechargeNum = rechargeInfoDao.queryRechargeInfoNum(rechargeId);
        if (rechargeNum < 1) {
            userInfosCreatorService.processCardAboutInfos(recharge.getCardId());
            createRechargeInfo(recharge);
        } else {
            LOGGER.info("充值记录【{}】已创建", rechargeId);
        }
        return recharge;
    }

    /**
     * 构建充值信息记录
     *
     * @param transin DZZF充值记录
     * @return 充值信息记录
     */
    Recharge buildRechargeInfo(TransIn transin) {
        String clientNo = transin.getClientNO();
        Organization org = transferUserInfoDao.queryOrganizationByNo(clientNo);
        if (org == null) {
            LOGGER.info("网点编号{}无对应的渠道ID", clientNo);
            return null;
        }
        String channelId = org.getChannelId();
        if (StringUtils.isEmpty(channelId)) {
            LOGGER.info("渠道ID为空，网点信息：{}", org);
            return null;
        }
        Integer channelType = BusinessUtils.convertChannelType(org.getAgencyType());
        String transTime = DateFormatUtils.format(transin.getOptOn(), DEFAULT_DATETIME_PATTERN);
        Integer exserialNum = baseInfoService.getExserialNum(transTime, transinSeqNoMap);
        StringBuilder exserialStr = new StringBuilder(exserialNum.toString());
        while (exserialStr.length() < DEFAULT_SEQNO_LENGTH) {
            exserialStr.insert(0, '0');
        }
        String id = channelType + channelId + transTime + exserialStr;
        Long money = transin.getIncMny().multiply(DEFAULT_FEN_VALUE).longValue();
        Recharge recharge = new Recharge();
        recharge.setId(id);
        recharge.setCardId(transin.getCardNetID() + transin.getECardNO());
        recharge.setGiftAmount(0L);
        recharge.setPaidAmount(money);
        recharge.setRechargeAmount(money);
        return recharge;
    }


    /**
     * 创建充值记录信息
     *
     * @param recharge 充值记录
     */
    private void createRechargeInfo(Recharge recharge) {
        try {
            transferUserInfoDao.createTestObjcet(recharge);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            LOGGER.info("错误的充值信息{}", recharge.toString());
        }
    }

    private void setDateStrs(List<String> dateStrs) {
        this.dateStrs = dateStrs;
    }

    public static void main(String[] args) {
        @SuppressWarnings("resource")
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        RechargeInfosCreatorService service = context.getBean(RechargeInfosCreatorService.class);
        service.setDateStrs(Arrays.asList(args));
        service.processRechargeInfos();
    }

}
